package be.teletask.onvif.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.*;

import java.io.File;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.List;

public class XmlToJsonUtils {


    public static void main(String[] args) throws Exception {
        // String xmlStr= readFile("D:/ADA/et/Issue_20130506_back.xml");
        String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<batch_status_response status=\"OK\">"
            + "<batch_id>DC3F089A-8E98-4B98-9434-0DF0EE937DC8</batch_id>" + "<offer status=\"OK\">"
            + "<product_fnac_id>2499187</product_fnac_id>"
            + "<offer_fnac_id>E473361D-683B-2A26-E878-F43816B9E111</offer_fnac_id>"
            + "<offer_seller_id>561C-385-9BE</offer_seller_id>" + "</offer>" + "<offer status=\"OK\">"
            + "<product_fnac_id>9784515</product_fnac_id>"
            + "<offer_fnac_id>4EF5F02D-8A87-9502-95F5-14881CDEEF8A</offer_fnac_id>"
            + "<offer_seller_id>B067-F0D-75E</offer_seller_id>" + "</offer>" + "<offer status=\"OK\">"
            + "<product_fnac_id>20005761</product_fnac_id>"
            + "<offer_fnac_id>B42974D3-D5E0-DAF1-629C-60541775D944</offer_fnac_id>"
            + "<offer_seller_id>B76A-CD5-153</offer_seller_id>" + "</offer>" + "</batch_status_response>";

        String xml2 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
            + "<env:Envelope xmlns:env=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:soapenc=\"http://www.w3.org/2003/05/soap-encoding\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:tt=\"http://www.onvif.org/ver10/schema\" xmlns:tds=\"http://www.onvif.org/ver10/device/wsdl\" xmlns:trt=\"http://www.onvif.org/ver10/media/wsdl\" xmlns:timg=\"http://www.onvif.org/ver20/imaging/wsdl\" xmlns:tev=\"http://www.onvif.org/ver10/events/wsdl\" xmlns:tptz=\"http://www.onvif.org/ver20/ptz/wsdl\" xmlns:tan=\"http://www.onvif.org/ver20/analytics/wsdl\" xmlns:tst=\"http://www.onvif.org/ver10/storage/wsdl\" xmlns:ter=\"http://www.onvif.org/ver10/error\" xmlns:dn=\"http://www.onvif.org/ver10/network/wsdl\" xmlns:tns1=\"http://www.onvif.org/ver10/topics\" xmlns:tmd=\"http://www.onvif.org/ver10/deviceIO/wsdl\" xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl\" xmlns:wsoap12=\"http://schemas.xmlsoap.org/wsdl/soap12\" xmlns:http=\"http://schemas.xmlsoap.org/wsdl/http\" xmlns:d=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\" xmlns:wsadis=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\" xmlns:wsnt=\"http://docs.oasis-open.org/wsn/b-2\" xmlns:wsa=\"http://www.w3.org/2005/08/addressing\" xmlns:wstop=\"http://docs.oasis-open.org/wsn/t-1\" xmlns:wsrf-bf=\"http://docs.oasis-open.org/wsrf/bf-2\" xmlns:wsntw=\"http://docs.oasis-open.org/wsn/bw-2\" xmlns:wsrf-rw=\"http://docs.oasis-open.org/wsrf/rw-2\" xmlns:wsaw=\"http://www.w3.org/2006/05/addressing/wsdl\" xmlns:wsrf-r=\"http://docs.oasis-open.org/wsrf/r-2\" xmlns:trc=\"http://www.onvif.org/ver10/recording/wsdl\" xmlns:tse=\"http://www.onvif.org/ver10/search/wsdl\" xmlns:trp=\"http://www.onvif.org/ver10/replay/wsdl\" xmlns:tnsn=\"http://www.eventextension.com/2011/event/topics\" xmlns:extwsd=\"http://www.onvifext.com/onvif/ext/ver10/wsdl\" xmlns:extxsd=\"http://www.onvifext.com/onvif/ext/ver10/schema\" xmlns:tas=\"http://www.onvif.org/ver10/advancedsecurity/wsdl\">"
            + "<env:Body>" + "	<tds:GetNTPResponse>" + "		<tds:NTPInformation>"
            + "			<tt:FromDHCP>false</tt:FromDHCP>" + "				<tt:NTPManual>"
            + "					<tt:Type>IPv4</tt:Type>"
            + "					<tt:IPv4Address>102.7.1.1</tt:IPv4Address>" + "				</tt:NTPManual>"
            + "		</tds:NTPInformation>" + "	</tds:GetNTPResponse>" + "</env:Body>" + "</env:Envelope>";

        /**
         * JSONObject json = xmlToJson(xml2); // System.out.println(json); JSONObject GetNTPResponse =
         * json.getJSONObject("GetNTPResponse"); JSONObject NTPInformation =
         * GetNTPResponse.getJSONObject("NTPInformation"); boolean FromDHCP = NTPInformation.getBoolean("FromDHCP"); //
         * System.out.println("FromDHCP:" + FromDHCP); JSONObject NTPManual = NTPInformation.getJSONObject("NTPManual");
         * String Type = NTPInformation.getString("Type"); String IPv4Address = NTPInformation.getString("IPv4Address");
         * // System.out.println("Type:" + Type + " IPv4Address:" + IPv4Address);
         * 
         * testErrorCodeMsg();
         * 
         * String timeXml = new String( "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?><s:Envelope
         * xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:sc=\"http://www.w3.org/2003/05/soap-encoding\"
         * xmlns:tt=\"http://www.onvif.org/ver10/schema\"
         * xmlns:tds=\"http://www.onvif.org/ver10/device/wsdl\"><s:Header/><s:Body><tds:GetSystemDateAndTimeResponse><tds:SystemDateAndTime><tt:DateTimeType>NTP</tt:DateTimeType><tt:DaylightSavings>false</tt:DaylightSavings><tt:TimeZone><tt:TZ>GMT+08:00</tt:TZ></tt:TimeZone><tt:UTCDateTime><tt:Time><tt:Hour>6</tt:Hour><tt:Minute>38</tt:Minute><tt:Second>24</tt:Second></tt:Time><tt:Date><tt:Year>2020</tt:Year><tt:Month>4</tt:Month><tt:Day>28</tt:Day></tt:Date></tt:UTCDateTime><tt:LocalDateTime><tt:Time><tt:Hour>14</tt:Hour><tt:Minute>38</tt:Minute><tt:Second>24</tt:Second></tt:Time><tt:Date><tt:Year>2020</tt:Year><tt:Month>4</tt:Month><tt:Day>28</tt:Day></tt:Date></tt:LocalDateTime></tds:SystemDateAndTime></tds:GetSystemDateAndTimeResponse></s:Body></s:Envelope>"
         * + "");
         * 
         * JSONObject timeObject = xmlToJson(timeXml); System.out.println(timeObject);
         */
        String x404 = new String(
            "{\"head\":{\"title\":\"Document Error: Not Found\"},\"body\":{\"p\":\"Request Refuse: ONVIF integrate function is disabled.\",\"h2\":\"Access Error: 404 -- Not Found\"}}");

        System.out.println(xmlToJson(x404).getString("p"));
    }

    public static void testErrorCodeMsg() {
        String errorMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
            + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:SOAP-ENC=\"http://www.w3.org/2003/05/soap-encoding\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:c14n=\"http://www.w3.org/2001/10/xml-exc-c14n#\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\" xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:wsa5=\"http://www.w3.org/2005/08/addressing\" xmlns:xmime=\"http://tempuri.org/xmime.xsd\" xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" xmlns:wsrfbf=\"http://docs.oasis-open.org/wsrf/bf-2\" xmlns:wstop=\"http://docs.oasis-open.org/wsn/t-1\" xmlns:tt=\"http://www.onvif.org/ver10/schema\" xmlns:wsrfr=\"http://docs.oasis-open.org/wsrf/r-2\" xmlns:aa=\"http://www.axis.com/vapix/ws/action1\" xmlns:aev=\"http://www.axis.com/vapix/ws/event1\" xmlns:ali1=\"http://www.axis.com/vapix/ws/light/CommonBinding\" xmlns:ali2=\"http://www.axis.com/vapix/ws/light/IntensityBinding\" xmlns:ali3=\"http://www.axis.com/vapix/ws/light/AngleOfIlluminationBinding\" xmlns:ali4=\"http://www.axis.com/vapix/ws/light/DayNightSynchronizeBinding\" xmlns:ali=\"http://www.axis.com/vapix/ws/light\" xmlns:tan1=\"http://www.onvif.org/ver20/analytics/wsdl/RuleEngineBinding\" xmlns:tan2=\"http://www.onvif.org/ver20/analytics/wsdl/AnalyticsEngineBinding\" xmlns:tan=\"http://www.onvif.org/ver20/analytics/wsdl\" xmlns:tds=\"http://www.onvif.org/ver10/device/wsdl\" xmlns:tev1=\"http://www.onvif.org/ver10/events/wsdl/NotificationProducerBinding\" xmlns:tev2=\"http://www.onvif.org/ver10/events/wsdl/EventBinding\" xmlns:tev3=\"http://www.onvif.org/ver10/events/wsdl/SubscriptionManagerBinding\" xmlns:wsnt=\"http://docs.oasis-open.org/wsn/b-2\" xmlns:tev4=\"http://www.onvif.org/ver10/events/wsdl/PullPointSubscriptionBinding\" xmlns:tev=\"http://www.onvif.org/ver10/events/wsdl\" xmlns:timg=\"http://www.onvif.org/ver20/imaging/wsdl\" xmlns:tptz=\"http://www.onvif.org/ver20/ptz/wsdl\" xmlns:trt=\"http://www.onvif.org/ver10/media/wsdl\" xmlns:ter=\"http://www.onvif.org/ver10/error\" xmlns:tns1=\"http://www.onvif.org/ver10/topics\" xmlns:tnsaxis=\"http://www.axis.com/2009/event/topics\"><SOAP-ENV:Body><SOAP-ENV:Fault><SOAP-ENV:Code><SOAP-ENV:Value>SOAP-ENV:Sender</SOAP-ENV:Value><SOAP-ENV:Subcode><SOAP-ENV:Value>ter:NotAuthorized</SOAP-ENV:Value></SOAP-ENV:Subcode></SOAP-ENV:Code><SOAP-ENV:Reason><SOAP-ENV:Text xml:lang=\"en\">Sender not authorized</SOAP-ENV:Text></SOAP-ENV:Reason><SOAP-ENV:Detail><SOAP-ENV:Text>The action requested requires authorization and the sender is not authorized</SOAP-ENV:Text></SOAP-ENV:Detail></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>"
            + "";

        System.out.println(errorMsg);
        JSONObject obj = xmlToJson(errorMsg);
        System.out.println(obj);
    }

    public static JSONObject xmlToJson(String xml) {
        if (StringUtils.isEmpty(xml)) {
            return null;
        }
        xml = xml.trim();
        Document doc;
        try {
            doc = DocumentHelper.parseText(xml);
            JSONObject json = new JSONObject();
            dom4j2Json(doc.getRootElement(), json);
            System.out.println("xml2Json:" + json.toJSONString());
            if (xml.contains("Body")) {
                return json.getJSONObject("Body");
            } else if (xml.contains("body")) {
                return json.getJSONObject("body");
            }

        } catch (DocumentException e) {
            e.printStackTrace();
            System.out.println("数据解析失败");
        }
        return null;

    }

    public static String readFile(String path) throws Exception {
        File file = new File(path);
        FileInputStream fis = new FileInputStream(file);
        FileChannel fc = fis.getChannel();
        ByteBuffer bb = ByteBuffer.allocate(new Long(file.length()).intValue());
        // fc向buffer中读入数据
        fc.read(bb);
        bb.flip();
        String str = new String(bb.array(), "UTF8");
        fc.close();
        fis.close();
        return str;

    }

    /**
     * xml转json
     *
     * @param element
     * @param json
     */
    public static void dom4j2Json(Element element, JSONObject json) {
        // 如果是属性 属性名以@开头
        for (Object o : element.attributes()) {
            Attribute attr = (Attribute)o;
            if (!isEmpty(attr.getValue())) {
                json.put("@" + attr.getName(), attr.getValue());
            }
        }
        List<Element> chdEl = element.elements();
        if (chdEl.isEmpty() && !isEmpty(element.getText())) {// 如果没有子元素,只有一个值
            json.put(element.getName(), element.getText());
        }

        for (Element e : chdEl) {// 有子元素
            if (!e.elements().isEmpty()) {// 子元素也有子元素
                JSONObject chdjson = new JSONObject();
                dom4j2Json(e, chdjson);
                Object o = json.get(e.getName());
                if (o != null) {
                    JSONArray jsona = null;
                    if (o instanceof JSONObject) {// 如果此元素已存在,则转为jsonArray
                        JSONObject jsono = (JSONObject)o;
                        json.remove(e.getName());
                        jsona = new JSONArray();
                        jsona.add(jsono);
                        jsona.add(chdjson);
                    }
                    if (o instanceof JSONArray) {
                        jsona = (JSONArray)o;
                        jsona.add(chdjson);
                    }
                    json.put(e.getName(), jsona);
                } else {
                    if (!chdjson.isEmpty()) {
                        json.put(e.getName(), chdjson);
                    }
                }

            } else {// 子元素没有子元素
                for (Object o : element.attributes()) {
                    Attribute attr = (Attribute)o;
                    if (!isEmpty(attr.getValue())) {
                        json.put("@" + attr.getName(), attr.getValue());
                    }
                }
                if (!e.getText().isEmpty()) {
                    json.put(e.getName(), e.getText());
                }
            }
        }
    }

    public static boolean isEmpty(String str) {

        if (str == null || str.trim().isEmpty() || "null".equals(str)) {
            return true;
        }
        return false;
    }
}
